`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 12/18/2024 04:56:17 PM
// Design Name: 
// Module Name: tb_axi_gt_common_sdm
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module tb_axi_gt_common_sdm;

    // Parameters
    parameter ADDR_WIDTH = 32;
    parameter DATA_WIDTH = 32;

    reg         fbclk      = 1'b0;
    reg         sys_clk    = 1'b0;
    reg         gtrefclk00 = 1'b0;
    reg         gtrefclk01 = 1'b0;
    reg         jesd_core_clk = 1'b0;
    reg         qpll0reset = 1'b0;

    wire        qpll0lock_out;
    wire        qpll0outclk_out;
    wire        qpll0outrefclk_out;
    
    wire        txoutclk;
    wire        rxoutclk;
    //wire        rxoutclk_O;

    // AXI Signals
    reg                               s_axi_aclk = 0;
    reg                               s_axi_aresetn = 1;
    // AXI Write Address Channel
    reg                               s_axi_awvalid = 0;
    reg          [ADDR_WIDTH-1:0]     s_axi_awaddr = 0;
    reg                    [ 2:0]     s_axi_awprot = 3'b010;
    wire                              s_axi_awready ;
    // AXI Write Data Channel
    reg                               s_axi_wvalid = 0;
    reg          [DATA_WIDTH-1:0]     s_axi_wdata = 0;
    reg          [(DATA_WIDTH/8)-1:0] s_axi_wstrb = 0;
    wire                              s_axi_wready ;
    // AXI Write Response Channel
    wire                              s_axi_bvalid ;
    wire                   [ 1:0]     s_axi_bresp ;
    reg                               s_axi_bready = 0;

    reg                               s_axi_arvalid = 0;
    reg          [ADDR_WIDTH-1:0]     s_axi_araddr = 0;
    reg                    [ 2:0]     s_axi_arprot = 0;
    wire                              s_axi_arready ;

    wire                              s_axi_rvalid ;
    wire         [DATA_WIDTH-1:0]     s_axi_rdata ;
    wire                   [ 1:0]     s_axi_rresp ;
    reg                               s_axi_rready = 0;

    //----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
    axi_gt_common_sdm axi_gt_common_sdm_inst (
        .fbclk                  (fbclk                   ),   
        .sys_clk                (txoutclk                ),
        //.sys_clk                (sys_clk                 ),    
        .gtrefclk00             (gtrefclk00              ),   
        .gtrefclk01             (gtrefclk01              ),   

        .txn_out                (txn_out                 ),
        .txp_out                (txp_out                 ),
        .rxoutclk_out           (rxoutclk                ),
        .txoutclk_out           (txoutclk                ),
        .qpll0reset             (1'b0                    ),
        .qpll0lock_out          (qpll0lock_out           ),    
        .qpll0outclk_out        (qpll0outclk_out         ),   
        .qpll0outrefclk_out     (qpll0outrefclk_out      ),
        
        .s_axi_aclk             (s_axi_aclk              ),
        .s_axi_aresetn          (s_axi_aresetn           ),

        .s_axi_awvalid          (s_axi_awvalid           ),
        .s_axi_awaddr           (s_axi_awaddr            ),
        .s_axi_awprot           (s_axi_awprot            ),
        .s_axi_awready          (s_axi_awready           ),

        .s_axi_wvalid           (s_axi_wvalid            ),
        .s_axi_wdata            (s_axi_wdata             ),
        .s_axi_wstrb            (s_axi_wstrb             ),
        .s_axi_wready           (s_axi_wready            ),

        .s_axi_bvalid           (s_axi_bvalid            ),
        .s_axi_bresp            (s_axi_bresp             ),
        .s_axi_bready           (s_axi_bready            ),

        .s_axi_arvalid          (s_axi_arvalid           ),
        .s_axi_araddr           (s_axi_araddr            ),
        .s_axi_arprot           (s_axi_arprot            ),
        .s_axi_arready          (s_axi_arready           ),

        .s_axi_rvalid           (s_axi_rvalid            ),
        .s_axi_rdata            (s_axi_rdata             ),
        .s_axi_rresp            (s_axi_rresp             ),
        .s_axi_rready           (s_axi_rready            ));
    // INST_TAG_END ------ End INSTANTIATION Template ---------
   
    // Clock Generation
    initial begin
        fbclk = 0;
        //forever #8.138 fbclk = ~fbclk; // 61.44 MHz clock
        //forever #6.667 fbclk = ~fbclk; // 75 MHz clock
        forever #5.000 fbclk = ~fbclk; // 100 MHz clock
    end
    initial begin
        s_axi_aclk = 0;
        forever #5.000 s_axi_aclk = ~s_axi_aclk; // 100 MHz clock
    end
    initial begin
        gtrefclk01 = 0;
        forever #5.000 gtrefclk01 = ~gtrefclk01; // 100 MHz clock
    end
    initial begin
        gtrefclk00 = 0;
        forever #2.035 gtrefclk00 = ~gtrefclk00; // 245.76 MHz clock
    end
    initial begin
        sys_clk = 0;
        forever #1.808 sys_clk = ~sys_clk; // 276.48 MHz clock
        //forever #1.667 sys_clk = ~sys_clk; // 300 MHz clock
        //forever #2.034 sys_clk = ~sys_clk; // 245.76 MHz clock
    end
    initial begin
        jesd_core_clk = 0;
        //forever #2.034 jesd_core_clk = ~jesd_core_clk; // 245.76 MHz clock
        forever #1.808 jesd_core_clk = ~jesd_core_clk; // 276.48 MHz clock
    end

    // Test Procedure
    initial begin
        // Reset
        #10
        s_axi_aresetn = 0;
        #10;
        s_axi_aresetn = 1;
        
        // Wait for reset deassertion
        repeat(500) @(posedge s_axi_aclk);
        write_address(32'h8009_1000, 32'h978D40);
        repeat(100) @(posedge s_axi_aclk);
        write_address(32'h8009_1000, 32'h0);
        repeat(100) @(posedge s_axi_aclk);
        write_address(32'h8009_1000, 32'hffffff);
        repeat(100) @(posedge s_axi_aclk);
        write_address(32'h8009_1000, 32'hfffff);
        write_address(32'h8009_1000, 32'hffff);
        write_address(32'h8009_1000, 32'hff);
        read_address(32'h8009_1000);
    end

    // task read_address;
    task read_address;
        input [31:0] addr;  // 
        begin
            if (addr[31:12] == 20'h8009_1) begin
                //**********************************step 3: read 0x8006_0000 *******************************
                // Read Operation
                s_axi_araddr = addr;   // Address to read
                s_axi_arprot = 3'b010;       // Protection type
                s_axi_arvalid = 1;           // Indicate address valid
                s_axi_rready = 1;            // Indicate ready for response
                
                // Wait for the address handshake
                @(posedge s_axi_aclk);
                while (!s_axi_arready) @(posedge s_axi_aclk);
                s_axi_arvalid = 0;           // Deassert valid after handshake
                
                // Wait for the read data
                @(posedge s_axi_aclk);
                while (!s_axi_rvalid) @(posedge s_axi_aclk);
                s_axi_rready = 0;            // Deassert after receiving data
                repeat(20) @(posedge s_axi_aclk);
            end
            //$display("Read from address %h: data = %h", addr, data); 
        end
    endtask
    // task write_address;
    task write_address;
        input [31:0] addr;      
        input [31:0] data_val;  
        begin
            //**********************************step 1: write 0x1 to 0x8006_0000***************
            // Write Operation
            if (addr[31:12] == 20'h8009_1) begin
                s_axi_awaddr = addr;   // Address to write
                s_axi_awprot = 3'b010;       // Protection type
                s_axi_awvalid = 1;           // Indicate address valid
                s_axi_wdata = data_val;        // Data to write
                s_axi_wstrb = 4'b1111;       // Write strobes
                s_axi_wvalid = 1;            // Indicate data valid
                s_axi_bready = 1;            // Indicate ready for response
                
                // Wait for the address handshake
                @(posedge s_axi_aclk);
                while (!s_axi_awready) @(posedge s_axi_aclk);
                s_axi_awvalid = 0;           // Deassert valid after handshake

                // Wait for the write data handshake
                while (!s_axi_wready) @(posedge s_axi_aclk);
                s_axi_wvalid = 0;            // Deassert valid after handshake

                @(posedge s_axi_aclk);
                while (!s_axi_bvalid) @(posedge s_axi_aclk);
                s_axi_bready = 0;            // Deassert after receiving response
                repeat(10) @(posedge s_axi_aclk);
            end 
        end
    endtask

endmodule
// ****************** Generate the required files to support the simulation ******************
/*
jesd204_phy_static_line_rate

create_ip -name jesd204_phy -vendor xilinx.com -library ip -version 4.1 -module_name jesd204_phy_s
set_property -dict [list \
  CONFIG.GT_Line_Rate {11.0592} \
  CONFIG.GT_REFCLK_FREQ {245.76} \
  CONFIG.RX_GT_Line_Rate {11.0592} \
  CONFIG.RX_GT_REFCLK_FREQ {245.76} \
  CONFIG.SupportLevel {0} \
] [get_ips jesd204_phy_s]

jesd204_phy_dynamic_line_rate
create_ip -name jesd204_phy -vendor xilinx.com -library ip -version 4.1 -module_name jesd204_phy_d
set_property -dict [list \
  CONFIG.Config_Type {1} \
  CONFIG.GT_Line_Rate {11.0592} \
  CONFIG.GT_REFCLK_FREQ {245.76} \
  CONFIG.RX_GT_Line_Rate {11.0592} \
  CONFIG.RX_GT_REFCLK_FREQ {245.76} \
  CONFIG.SupportLevel {0} \
] [get_ips jesd204_phy_d]

*/
// *******************************************************